package com.example.selfdefinescope;


import org.springframework.beans.factory.ObjectFactory;
import org.springframework.beans.factory.config.Scope;

import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;

// 自定义作用域Bean作用域
// Scope实现应该是线程安全的。
// 如果需要，一个Scope实例可以同时与多个 bean 工厂一起使用（除非它明确想要知道包含的 BeanFactory），任意数量的线程可以从任意数量的工厂同时访问Scope 。
public class CustomScope implements Scope {

    public static final String CUSTOM_SCOPE = "customScope";
    private final ConcurrentMap<String, Object> scopedObjects = new ConcurrentHashMap<>();

    // 根据 Bean 的名称获取作用域中的对象。如果该对象还不存在，ObjectFactory 将被用来创建它，并将创建的对象存储在作用域中。
    // name: 作用域中 Bean 的名称。
    // objectFactory: 用于创建 Bean 实例的工厂。
    // 返回值: 作用域中与指定名称相关联的对象。如果对象不存在，将使用 ObjectFactory 创建新对象并返回。
    // 说明: 这是获取作用域中对象的主要方法，它确保每个 Bean 名称在作用域中有唯一的实例，或者在第一次请求时创建该实例。
    @Override
    public Object get(String name, ObjectFactory<?> objectFactory) {
        System.out.println("CustomScope的get方法被调用，name参数：" + name);
        return scopedObjects.computeIfAbsent(name, k -> objectFactory.getObject());
    }

    // 从作用域中移除与指定名称相关联的对象。
    // name: 需要移除的 Bean 名称。
    // 返回值: 被移除的对象，如果不存在则返回 null。
    // 说明: 这个方法允许手动移除作用域中的对象，通常在作用域是 request 或 session 时用于清理对象。
    @Override
    public Object remove(String name) {
        System.out.println("CustomScope的remove方法被调用，name参数：" + name);
        return scopedObjects.remove(name);
    }

    // 注册一个回调函数，当作用域中的对象被销毁时执行。
    // name: 需要注册销毁回调的 Bean 名称。
    // callback: 当 Bean 被销毁时执行的回调函数
    // 这个方法允许在 Bean 销毁之前执行特定的清理逻辑。如果作用域是 request 或 session，则在这些生命周期结束时调用回调函数。
    @Override
    public void registerDestructionCallback(String name, Runnable callback) {
        // Optional: Implement if you need custom destruction behavior
    }

    // 根据指定的键解析作用域的上下文对象。
    // key: 上下文对象的键
    // 返回值: 与键相关联的上下文对象，如果不存在则返回 null。
    // 说明: 这个方法用于在特定作用域中解析上下文相关的对象。例如，在 session 作用域中，可以根据键访问与会话相关的附加数据。
    @Override
    public Object resolveContextualObject(String key) {
        return null;
    }

    // 返回当前基础范围的对话 ID （如果有）。
    // 对话 ID 的确切含义取决于底层存储机制。对于会话范围的对象，对话 ID 通常等于（或从session ID派生而来）；对于位于整个会话中的自定义对话，当前对话的特定 ID 是合适的。
    // 注意：这是可选操作。如果底层存储机制没有明显的此类 ID 候选者，则在此方法的实现中返回null是完全有效的。
    // 返回：对话 ID，如果当前范围没有对话 ID，则为null
    // 抛出：
    // IllegalStateException – 如果底层范围当前不活跃
    @Override
    public String getConversationId() {
        return null;
    }
}
